<template>
    <teleport to="body">
        <transition name="dialog-fade" @after-enter="onAfterEnter" @after-leave="onAfterLeave">
            <div
                v-if="visible"
                class="rambler-dialog-wrapper"
                :class="wrapperClass"
                :style="{ zIndex }"
                @click.self="handleMaskClick"
            >
                <div
                    ref="dialogRef"
                    class="rambler-dialog"
                    :class="dialogClass"
                    :style="dialogStyle"
                    tabindex="-1"
                    @keydown.esc="handleEsc"
                >

                    <!-- 标题栏 -->
                    <div class="rambler-dialog-header" @mousedown="startDrag">
                        <slot name="header">
                            <div class="rambler-dialog-title">{{ title }}</div>
                        </slot>
                        <slot name="close">
                            <button
                                v-if="closable"
                                class="rambler-dialog-close"
                                @click="handleClose"
                            >
                                <span class="rambler-dialog-close-x"></span>
                            </button>
                        </slot>
                    </div>

                    <!-- 内容区域 -->
                    <div class="rambler-dialog-body">
                        <slot></slot>
                    </div>

                    <!-- 底部操作栏 -->
                    <div class="rambler-dialog-footer" v-if="footer">
                        <slot name="footer">
                            <a-button
                                v-if="showCancel"
                                @click="handleCancel"
                                :loading="cancelLoading"
                            >
                                {{ cancelText }}
                            </a-button>
                            <a-button
                                v-if="showOk"
                                type="primary"
                                @click="handleOk"
                                :loading="okLoading"
                            >
                                {{ okText }}
                            </a-button>
                        </slot>
                    </div>
                </div>
            </div>
        </transition>
    </teleport>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'
import { Button as AButton } from 'ant-design-vue'


const startMouseX = ref(0)
const startMouseY = ref(0)
const startDialogX = ref(0)
const startDialogY = ref(0)


// 定义 props
interface Props {
    visible?: boolean
    title?: string
    width?: string | number
    closable?: boolean
    maskClosable?: boolean
    draggable?: boolean
    okText?: string
    cancelText?: string
    showOk?: boolean
    showCancel?: boolean
    okLoading?: boolean
    cancelLoading?: boolean
    mask?: boolean
    keyboard?: boolean
    centered?: boolean
    wrapClassName?: string
    zIndex?: number
    closeOnEsc?: boolean
    forceRender?: boolean
    footer?: boolean
}

const props = withDefaults(defineProps<Props>(), {
    visible: false,
    title: '',
    width: 520,
    closable: true,
    maskClosable: true,
    draggable: false,
    okText: '确定',
    cancelText: '取消',
    showOk: true,
    showCancel: true,
    okLoading: false,
    cancelLoading: false,
    mask: true,
    keyboard: true,
    centered: false,
    wrapClassName: '',
    zIndex: 1000,
    closeOnEsc: true,
    forceRender: false,
    footer: true
})

// 定义 emits
const emit = defineEmits<{
    (e: 'update:visible', visible: boolean): void
    (e: 'ok'): void
    (e: 'cancel'): void
    (e: 'close'): void
}>()

// 响应式数据
const dialogRef = ref<HTMLElement | null>(null)
const isDragging = ref(false)
const dialogPosition = ref({ x: 10, y: 10 })
const lastFocusedElement = ref<HTMLElement | null>(null)

// 计算属性
const wrapperClass = computed(() => [
    'rambler-dialog-wrapper',
    props.wrapClassName,
    {
        'rambler-dialog-centered': props.centered
    }
])

const dialogClass = computed(() => [
    'rambler-dialog',
    {
        'rambler-dialog-draggable': props.draggable
    }
])

const dialogStyle = computed(() => {
    const styles: Record<string, string> = {}

    // 宽度处理
    if (props.width !== undefined) {
        if (typeof props.width === 'number') {
            styles.width = `${props.width}px`
        } else {
            styles.width = props.width
        }
    }

    // 拖拽位置
    if (props.draggable) {
        styles.transform = `translate(${dialogPosition.value.x}px, ${dialogPosition.value.y}px)`
    }

    return styles
})

// 方法
const updateVisible = (visible: boolean) => {
    emit('update:visible', visible)
}

const handleClose = () => {
    updateVisible(false)
    emit('close')
}

const handleOk = () => {
    emit('ok')
}

const handleCancel = () => {
    emit('cancel')
    updateVisible(false)
}

const handleMaskClick = () => {
    if (props.maskClosable) {
        handleClose()
    }
}

const handleEsc = (e: KeyboardEvent) => {
    if (props.closeOnEsc && props.keyboard) {
        e.preventDefault()
        handleClose()
    }
}

const startDrag = (e: MouseEvent) => {
    if (!props.draggable) return

    isDragging.value = true

    // 记录鼠标按下时的位置
    startMouseX.value = e.clientX
    startMouseY.value = e.clientY

    // 记录弹窗当时的位置
    startDialogX.value = dialogPosition.value.x
    startDialogY.value = dialogPosition.value.y

    document.addEventListener('mousemove', onDrag)
    document.addEventListener('mouseup', stopDrag)
}

const onDrag = (e: MouseEvent) => {
    if (!isDragging.value || !dialogRef.value) return

    const deltaX = e.clientX - startMouseX.value
    const deltaY = e.clientY - startMouseY.value

    let newX = startDialogX.value + deltaX
    let newY = startDialogY.value + deltaY

    // 限制范围
    const dialogWidth = dialogRef.value.offsetWidth
    const dialogHeight = dialogRef.value.offsetHeight
    const winWidth = window.innerWidth
    const winHeight = window.innerHeight

    // 左右边界
    const minX = -(dialogWidth - 100) // 左边至少留 100px
    const maxX = winWidth - 100
    // 上下边界
    const minY = 0
    const maxY = winHeight - 50

    if (newX < minX) newX = minX
    if (newX > maxX) newX = maxX
    if (newY < minY) newY = minY
    if (newY > maxY) newY = maxY

    dialogPosition.value = { x: newX, y: newY }
}

const stopDrag = () => {
    isDragging.value = false
    document.removeEventListener('mousemove', onDrag)
    document.removeEventListener('mouseup', stopDrag)
}

// 添加一个方法来重置位置
const resetPosition = () => {
    dialogPosition.value = { x: 0, y: 0 }
}

const onAfterEnter = () => {
    // 保存焦点元素
    lastFocusedElement.value = document.activeElement as HTMLElement

    // 聚焦到弹窗
    if (dialogRef.value) {
        dialogRef.value.focus()
    }

    // 禁止背景滚动
    document.body.style.overflow = 'hidden'

    // 重置位置
    resetPosition()
}

const onAfterLeave = () => {
    // 恢复焦点
    if (lastFocusedElement.value) {
        lastFocusedElement.value.focus()
    }

    // 恢复背景滚动
    document.body.style.overflow = ''

    // 重置拖拽位置
    resetPosition()
}

// 监听 visible 变化
watch(() => props.visible, (newVal) => {
    if (newVal) {
        nextTick(() => {
            if (dialogRef.value) {
                dialogRef.value.focus()
            }
        })
    }
})

// 组件卸载时清理
onUnmounted(() => {
    document.body.style.overflow = ''
})
</script>

<style lang="less">
.rambler-dialog-wrapper {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    overflow: hidden;
    outline: 0;
    z-index: 1000;

    &.rambler-dialog-centered {
        display: flex;
        align-items: center;
        justify-content: center;

        .rambler-dialog {
            margin: 0 auto;
        }
    }
}

.rambler-dialog {
    position: relative;
    margin: 100px auto;
    background: #fff;
    border-radius: 6px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    outline: none;

    &.rambler-dialog-draggable {
        margin: 0;
    }
}

.rambler-dialog-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 24px;
    border-bottom: 1px solid #f0f0f0;
    border-radius: 6px 6px 0 0;
    cursor: move;   // ✅ 加上鼠标样式
}

.rambler-dialog-title {
    font-size: 16px;
    font-weight: 500;
    line-height: 1.4;
    color: rgba(0, 0, 0, 0.85);
}

.rambler-dialog-close {
    position: absolute;
    top: 16px;
    right: 16px;
    padding: 0;
    background: transparent;
    border: 0;
    outline: 0;
    cursor: pointer;
    transition: color 0.3s;
    z-index: 2;

    .rambler-dialog-close-x {
        display: block;
        width: 16px;
        height: 16px;
        background: transparent;

        &::before {
            position: absolute;
            top: 0;
            left: 0;
            width: 16px;
            height: 16px;
            background: rgba(0, 0, 0, 0.45);
            border-radius: 50%;
            content: '';
            transition: background 0.3s;
        }

        &::after {
            position: absolute;
            top: 50%;
            left: 50%;
            width: 8px;
            height: 1px;
            background: #fff;
            content: '';
            transform: translate(-50%, -50%) rotate(45deg);
        }

        &::before,
        &::after {
            pointer-events: none;
        }
    }

    &:hover .rambler-dialog-close-x::before {
        background: rgba(0, 0, 0, 0.7);
    }
}

.rambler-dialog-body {
    padding: 24px;
    font-size: 14px;
    line-height: 1.5;
    color: rgba(0, 0, 0, 0.85);
    word-wrap: break-word;
}

.rambler-dialog-footer {
    padding: 10px 16px;
    text-align: right;
    background: transparent;
    border-top: 1px solid #f0f0f0;
    border-radius: 0 0 6px 6px;

    button + button {
        margin-left: 8px;
    }
}

// 动画效果
.dialog-fade-enter-active,
.dialog-fade-leave-active {
    transition: opacity 0.3s;

    .rambler-dialog {
        transition: transform 0.3s, opacity 0.3s;
    }
}

.dialog-fade-enter-from,
.dialog-fade-leave-to {
    opacity: 0;

    .rambler-dialog {
        transform: scale(0.8);
        opacity: 0;
    }
}

.dialog-fade-enter-to,
.dialog-fade-leave-from {
    opacity: 1;

    .rambler-dialog {
        transform: scale(1);
        opacity: 1;
    }
}

// 响应式设计
@media (max-width: 768px) {
    .rambler-dialog {
        width: calc(100vw - 32px) !important;
        margin: 16px auto;
    }

    .rambler-dialog-body {
        padding: 16px;
    }
}
</style>
